package com.ziytek.web.citizen.service;

import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.model.bean.StatsFirstCache;
import io.netty.channel.ChannelHandlerContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.net.InetSocketAddress;
import java.util.Map;

/**
 * @author fenghx
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @__(@Autowired))
public class WebClientService {

    private String getClientIp(ChannelHandlerContext ctx) {
        return null == ctx ? null : ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
    }


    public void deleteCacheStatsFirst(ChannelHandlerContext ctx) {
        if (null == ctx) {
            return;
        }

        var clientIp = getClientIp(ctx);
        var port = ((InetSocketAddress) ctx.channel().remoteAddress()).getPort();

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_FIRST_PUSH + CaffeineUtil.CACHE_KEY_SYMBOL;

        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }

        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue().data instanceof StatsFirstCache statsFirstCache) {
                if (statsFirstCache.getCtx() == ctx) {
                    CaffeineUtil.delete(entry.getKey());
                }

                if (statsFirstCache.getCtx() != null) {
                    var clientIpOld = getClientIp(statsFirstCache.getCtx());
                    var portOld = ((InetSocketAddress) statsFirstCache.getCtx().channel().remoteAddress()).getPort();
                    if (clientIp.equals(clientIpOld) && port == portOld) {
                        CaffeineUtil.delete(entry.getKey());
                        log.info("web client channelInactive deleteCacheStatsFirst,client IP：{},portOld:{},name:{}", clientIp, portOld, ctx.name());
                    }
                }
            }
        }
    }

    public void deleteCacheStats(ChannelHandlerContext ctx) {
        if (null == ctx) {
            return;
        }

        var clientIp = getClientIp(ctx);
        var port = ((InetSocketAddress) ctx.channel().remoteAddress()).getPort();

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_QUERY;

        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }

        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue().data instanceof Map statsMap) {
                if (!CollectionUtils.isEmpty(statsMap) && statsMap.get("ctx") != null) {
                    var clientIpOld = getClientIp((ChannelHandlerContext) statsMap.get("ctx"));
                    var portOld = ((InetSocketAddress) ((ChannelHandlerContext) statsMap.get("ctx")).channel().remoteAddress()).getPort();
                    if (clientIp.equals(clientIpOld) && port == portOld) {
                        CaffeineUtil.delete(entry.getKey());
                        log.info("web client channelInactive deleteCacheStats,client IP：{},portOld:{},name:{}", clientIp, portOld, ctx.name());
                    }
                }
            }
        }
    }

    public void deleteOldCacheStats() {

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REAL_STATS_QUERY;

        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }

        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue().data instanceof Map statsMap) {
                if (!CollectionUtils.isEmpty(statsMap) && statsMap.get("ctx") != null) {
                    CaffeineUtil.delete(entry.getKey());
                    log.info("web client channelInactive deleteCacheStats old cache");
                }
            }
        }
    }

    public void deleteCacheRealTime(ChannelHandlerContext ctx) {
        if (null == ctx) {
            return;
        }

        var clientIp = getClientIp(ctx);
        var port = ((InetSocketAddress) ctx.channel().remoteAddress()).getPort();

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REALTIME_QUERY;

        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }

        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue().data instanceof Map statsMap) {
                if (!CollectionUtils.isEmpty(statsMap) && statsMap.get("ctx") != null) {
                    var clientIpOld = getClientIp((ChannelHandlerContext) statsMap.get("ctx"));
                    var portOld = ((InetSocketAddress) ((ChannelHandlerContext) statsMap.get("ctx")).channel().remoteAddress()).getPort();
                    if (clientIp.equals(clientIpOld) && port == portOld) {
                        CaffeineUtil.delete(entry.getKey());
                        log.info("首页实时数据推送缓存删除deleteCacheRealTime,client IP：{},portOld:{},name:{}", clientIp, portOld, ctx.name());
                    }
                }
            }
        }
    }

    public void deleteCacheOldRealTime() {

        var key = CaffeineUtil.CACHE_KEY_TOPIC_REALTIME_QUERY;

        Map<String, CaffeineUtil.CacheObject<?>> map = CaffeineUtil.getAllStartWith(key);
        if (CollectionUtils.isEmpty(map)) {
            return;
        }

        for (Map.Entry<String, CaffeineUtil.CacheObject<?>> entry : map.entrySet()) {
            if (entry.getValue().data instanceof Map statsMap) {
                if (!CollectionUtils.isEmpty(statsMap) && statsMap.get("ctx") != null) {
                    CaffeineUtil.delete(entry.getKey());
                    log.info("old首页实时数据推送缓存删除deleteCacheRealTime");
                }
            }
        }
    }
}
